
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <title>NES游戏开发</title>
    <link rel="stylesheet" href="index.css"/>
</head>

<body>

<div class="main">
<p><h1>附录，nesdoug库</h1>
</p><p>
</p><p>
</p><p>
</p><p>Under construction.
</p><p>
</p><p><pre>
</p><p>
</p><p>//Written by Doug Fraker 2018
</p><p>void set_vram_buffer(void);
</p><p>// sets the vram update to point to the vram_buffer. VRAM_BUF defined in crt0.s
</p><p>// this can be undone by set_vram_update(NULL)
</p><p>
</p><p>void __fastcall__ one_vram_buffer(unsigned char data, int ppu_address);
</p><p>// to push a single byte write to the vram_buffer
</p><p>
</p><p>void __fastcall__ multi_vram_buffer_horz(const char * data, unsigned char len, int ppu_address);
</p><p>// to push multiple writes as one sequential horizontal write to the vram_buffer
</p><p>
</p><p>void __fastcall__ multi_vram_buffer_vert(const char * data, unsigned char len, int ppu_address);
</p><p>// to push multiple writes as one sequential vertical write to the vram_buffer
</p><p>
</p><p>void clear_vram_buffer(void);
</p><p>// just sets the index into the vram buffer to zero
</p><p>// this should be done at the beginning of each frame, if using the vram_buffer
</p><p>
</p><p>unsigned char __fastcall__ get_pad_new(unsigned char pad);
</p><p>// pad 0 or 1, use AFTER pad_poll() to get the trigger / new button presses
</p><p>// more efficient than pad_trigger, which runs the entire pad_poll code again
</p><p>
</p><p>unsigned char __fastcall__ get_frame_count(void);
</p><p>// use this internal value to time events, this ticks up every frame
</p><p>
</p><p>void __fastcall__ set_music_speed(unsigned char tempo);
</p><p>// this will alter the tempo of music, range 1-12 are reasonable, low is faster
</p><p>// default is 6
</p><p>// music_play also sets the tempo, and any Fxx effect in the song will too
</p><p>// you will probably have to repeatedly set_music_speed() every frame
</p><p>// music_stop() and music_pause() also overwrite this value
</p><p>
</p><p>unsigned char __fastcall__ check_collision(void * object1, void * object2);
</p><p>// expects an object (struct) where the first 4 bytes are X, Y, width, height
</p><p>// you will probably have to pass the address of the object like &object
</p><p>// the struct can be bigger than 4 bytes, as long as the first 4 bytes are X, Y, width, height
</p><p>
</p><p>void __fastcall__ pal_fade_to(unsigned char from, unsigned char to);
</p><p>// adapted from Shiru’s “Chase” game code
</p><p>// values must be 0-8, 0 = all black, 8 = all white, 4 = normal
</p><p>
</p><p>void __fastcall__ set_scroll_x(unsigned int x);
</p><p>// x can be in the range 0-0x1ff, but any value would be fine, it discards higher bits
</p><p>
</p><p>void __fastcall__ set_scroll_y(unsigned int y);
</p><p>// y can be in the range 0-0x1ff, but any value would be fine, it discards higher bits
</p><p>// NOTE – different system than neslib (which needs y in range 0-0x1df)
</p><p>// the advantage here, is you can set Y scroll to 0xff (-1) to shift the screen down 1,
</p><p>// which aligns it with sprites, which are shifted down 1 pixel
</p><p>
</p><p>int __fastcall__ add_scroll_y(unsigned char add, unsigned int scroll);
</p><p>// add a value to y scroll, keep the low byte in the 0-0xef range
</p><p>// returns y scroll, which will have to be passed to set_scroll_y
</p><p>
</p><p>int __fastcall__ sub_scroll_y(unsigned char sub, unsigned int scroll);
</p><p>// subtract a value from y scroll, keep the low byte in the 0-0xef range
</p><p>// returns y scroll, which will have to be passed to set_scroll_y
</p><p>
</p><p>int __fastcall__ get_ppu_addr(char nt, char x, char y);
</p><p>// gets a ppu address from x and y coordinates (in pixels)
</p><p>// x is screen pixels 0-255, y is screen pixels 0-239, nt is nametable 0-3
</p><p>
</p><p>int __fastcall__ get_at_addr(char nt, char x, char y);
</p><p>// gets a ppu address in the attribute table from x and y coordinates (in pixels)
</p><p>// x is screen pixels 0-255, y is screen pixels 0-239, nt is nametable 0-3
</p><p>// the next 4 functions are for my metatile system, as described in my tutorial
</p><p>// nesdoug.com
</p><p>void __fastcall__ set_data_pointer(const char * data);
</p><p>// for the metatile system, pass it the addresses of the room data
</p><p>// room data should be exactly 240 bytes (16×15)
</p><p>// each byte represents a 16×16 px block of the screen
</p><p>
</p><p>void __fastcall__ set_mt_pointer(const char * metatiles);
</p><p>// for the metatile system, pass it the addresses of the metatile data
</p><p>// a metatile is a 16×16 px block
</p><p>// metatiles is variable length, 5 bytes per metatile…
</p><p>// TopL, TopR, BottomL, BottomR, then 1 byte of palette 0-3
</p><p>// max metatiles = 51 (because 51 x 5 = 255)
</p><p>
</p><p>void __fastcall__ buffer_1_mt(int ppu_address, char metatile);
</p><p>// will push 1 metatile and 0 attribute bytes to the vram_buffer
</p><p>// make sure to set_vram_buffer(), and clear_vram_buffer(),
</p><p>// and set_mt_pointer()
</p><p>// “metatile” should be 0-50, like the metatile data
</p><p>
</p><p>void __fastcall__ buffer_4_mt(int ppu_address, char index);
</p><p>// will push 4 metatiles (2×2 box) and 1 attribute byte to the vram_buffer
</p><p>// this affects a 32×32 px area of the screen, and pushes 17 bytes to the vram_buffer.
</p><p>// make sure to set_vram_buffer(), and clear_vram_buffer(),
</p><p>// set_data_pointer(), and set_mt_pointer()
</p><p>// “index” is which starting byte in the room data, to convert to tiles.
</p><p>// use index = (y & 0xf0) + (x >> 4); where x 0-255 and y 0-239;
</p><p>// index should be 0-239, like the room data it represents
</p><p>
</p><p>void flush_vram_update_nmi(void);
</p><p>// same as flush_vram_update, but assumes that a pointer to the vram has been set already
</p><p>// this is for when the screen is OFF, but you still want to write to the PPU
</p><p>// with the vram_buffer system
</p><p>// “nmi” is a misnomer. this doesn’t have to happen during nmi.
</p><p>
</p><p>void __fastcall__ color_emphasis(char color);
</p><p>// change the PPU’s color emphasis bits
</p><p>
</p><p>#define COL_EMP_BLUE 0x80
</p><p>#define COL_EMP_GREEN 0x40
</p><p>#define COL_EMP_RED 0x20
</p><p>#define COL_EMP_NORMAL 0x00
</p><p>#define COL_EMP_DARK 0xe0
</p><p>
</p><p>void __fastcall__ xy_split(unsigned int x, unsigned int y);
</p><p>// a version of split that actually changes the y scroll midscreen
</p><p>// requires a sprite zero hit, or will crash
</p><p>
</p><p>void gray_line(void);
</p><p>// For debugging. Insert at the end of the game loop, to see how much frame is left.
</p><p>// Will print a gray line on the screen. Distance to the bottom = how much is left.
</p><p>// No line, possibly means that you are in v-blank.
</p><p>
</p><p>#define high_byte(a) *((unsigned char*)&a+1)
</p><p>#define low_byte(a) *((unsigned char*)&a)
</p><p>// for getting or modifying just 1 byte of an int
</p><p>
</p><p>#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
</p><p>#define PEEK(addr) (*(unsigned char*) (addr))
</p><p>// examples
</p><p>// POKE(0xD800, 0x12); // stores 0x12 at address 0xd800, useful for hardware registers
</p><p>// B = PEEK(0xD800); // read a value from address 0xd800, into B, which should be a char
</p><p>
</p><p>void seed_rng(void);
</p><p>// get from the frame count. You can use a button (start on title screen) to trigger
</p><p>
</p><p></pre>
</p><p>
</p><p>
</p><p>
</p></div>
<script>
var h1 = document.getElementsByTagName("h1");
if(h1.length>0){
    document.title = h1[0].innerHTML;
}
</script>
</body>
</html>
